home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 101-125 / scopedisk122 / popup / source / main.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  11KB  |  378 lines

  1. #include "PopUpMenu.h"
  2. #include "Version.h"
  3.  
  4. #define REPLYPORTNAME  "Reply"
  5. #define IMPDEVPORTNAME "ImpDev"
  6. #define TIMERPORTNAME  "Timer"
  7. #define QUITPORTNAME   "Quit"
  8. #define INPHANDLNAME   PopUpTaskName
  9. #define SEMAPHORENAME  PopUpTaskName
  10.  
  11. #define POPUPMSG       "\x9B0;33mPopUpMenu\x9B0m "
  12. #define KILLMSG        "removed.\n"
  13. #define STARTMSG       "installed.\n\xA9 Martin Adrian 1990\n"
  14. #define FAILMSG        "failed.\n"
  15. #define DELAYTIME      150
  16.  
  17. #define INPHANDLPRI    53
  18. /* Must use kickstart 1.2 or higher */
  19. #define LIBVERSION     33
  20.  
  21. /* don't know how to find these in C */
  22. #define LVOSetMenuStrip   -0x108
  23. #define LVOClearMenuStrip -0x36
  24. #define LVOOnMenu      -0xc0
  25. #define LVOOffMenu      -0xb4
  26.  
  27. /* this is for errors in proto/exec.h */
  28. #undef RemSemaphore
  29. #pragma syscall RemSemaphore 25e 901
  30.  
  31. extern VOID InitPopUpMenu(VOID);
  32. extern VOID MySetMenuStrip();
  33. extern VOID MyClearMenuStrip();
  34. extern VOID MyOnMenu();
  35. extern VOID MyOffMenu();
  36.  
  37. VOID InitPopUpMenu()
  38. {
  39.  
  40.   IMPORT struct DosLibrary     *DosBase;
  41.   IMPORT struct IntuitionBase  *IntuitionBase;
  42.   IMPORT struct GfxBase        *GfxBase;
  43.   IMPORT struct LayersBase     *LayersBase;
  44.  
  45.   IMPORT struct IOStdReq       *InputReqBlock;
  46.   IMPORT struct timerequest    *TimerReqBlock;
  47.   IMPORT struct SignalSemaphore PopUpSemaphore;
  48.   IMPORT __fptr OldSetMenuStrip, OldClearMenuStrip, OldOnMenu, OldOffMenu;
  49.   IMPORT BPTR StdOut;
  50.   IMPORT BPTR PopUpSeg;
  51.  
  52.   IMPORT STRPTR far PopUpTaskName; /* Pointer to the string "PopUpMenu" */
  53.  
  54.   struct MsgPort      *ReplyPort;
  55.   struct MsgPort      *InputDevPort;
  56.   struct MsgPort      *TimerPort;
  57.   struct Interrupt    InputReqData;
  58.   struct SignalData   InputSignals;
  59.   LONG              MenuUpSigNum, MenuDownSigNum;
  60.   LONG              MouseMovedSigNum, SelectDownSigNum;
  61.  
  62.   geta4();   /* load global database */
  63.  
  64.   Write(StdOut,POPUPMSG,sizeof(POPUPMSG));
  65.  
  66.   /***********************************
  67.    * see if we are already installed *
  68.    ***********************************/
  69.   if (!(ReplyPort = FindPort(REPLYPORTNAME))) {
  70.     if (!(ReplyPort = CreatePort(REPLYPORTNAME,0)))
  71.       goto CleanUp13;
  72.   }
  73.   else {
  74.     /* yes, popupmenues already installed, tell running task to quit */
  75.     struct MsgPort *const QuitPort = CreatePort(QUITPORTNAME,0);
  76.     struct IntuiMessage *Message;
  77.  
  78.     if (QuitPort) {
  79.       if (Message = BuildIntuiMsg(QuitPort,QUITPOPUPMENU,NULL)) {
  80.     /* Send quitmessage */
  81.     PutMsg(ReplyPort, (struct Message *)Message);
  82.     /* Wait for reply */
  83.     WaitPort(QuitPort);
  84.     /* get rid of the message */
  85.     GetMsg(QuitPort);
  86.     FreeMem(Message,(LONG)Message->ExecMessage.mn_Length +
  87.                 sizeof(struct Message));
  88.  
  89.     WriteAndClose(KILLMSG, sizeof(KILLMSG));
  90.       }
  91.       DeletePort(QuitPort);
  92.     }
  93.     goto CleanUp13;
  94.   }
  95.  
  96.   /******************
  97.    * open libraries *
  98.    ******************/
  99.   if (!(IntuitionBase = (struct IntuitionBase *)
  100.             OpenLibrary("intuition.library", LIBVERSION)))
  101.     goto CleanUp12;
  102.   if (!(GfxBase       = (struct GfxBase *)
  103.             OpenLibrary("graphics.library", LIBVERSION)))
  104.     goto CleanUp11;
  105.   if (!(LayersBase    = (struct LayersBase *)
  106.             OpenLibrary("layers.library", LIBVERSION)))
  107.     goto CleanUp10;
  108.  
  109.   /************************
  110.    * Allocate our signals *
  111.    ************************/
  112.   if ((MenuUpSigNum     = AllocSignal(-1)) == -1)
  113.     goto CleanUp9;
  114.   if ((MenuDownSigNum   = AllocSignal(-1)) == -1)
  115.     goto CleanUp8;
  116.   if ((MouseMovedSigNum = AllocSignal(-1)) == -1)
  117.     goto CleanUp7;
  118.   if ((SelectDownSigNum = AllocSignal(-1)) == -1)
  119.     goto CleanUp6;
  120.  
  121.  /****************************************
  122.   * Build connection to the input.device *
  123.   ****************************************/
  124.   if (!(InputDevPort  = CreatePort(IMPDEVPORTNAME,0)))
  125.     goto CleanUp5;
  126.   if ((InputReqBlock = (struct IOStdReq *)
  127.                AllocMem(sizeof(struct IOStdReq),
  128.                MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
  129.     goto CleanUp4;
  130.  
  131.   InputReqBlock->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  132.   InputReqBlock->io_Message.mn_Length        = sizeof(struct IOStdReq);
  133.   InputReqBlock->io_Message.mn_ReplyPort    = InputDevPort;
  134.  
  135.   if (OpenDevice("input.device",0,(struct IORequest *)InputReqBlock,0))
  136.     goto CleanUp3;
  137.  
  138.   /****************************************
  139.    * Bulid connection to the timer.device *
  140.    ****************************************/
  141.   if (!(TimerPort = CreatePort(TIMERPORTNAME,0)))
  142.     goto CleanUp3x3;
  143.   if (!(TimerReqBlock = (struct timerequest *)
  144.                AllocMem(sizeof(struct timerequest),
  145.                MEMF_CLEAR | MEMF_PUBLIC)))
  146.     goto CleanUp3x2;
  147.  
  148.   TimerReqBlock->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  149.   TimerReqBlock->tr_node.io_Message.mn_Length        = sizeof(struct timerequest);
  150.   TimerReqBlock->tr_node.io_Message.mn_ReplyPort    = TimerPort;
  151.  
  152.   if (OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerReqBlock,0))
  153.     goto CleanUp3x1;
  154.  
  155.   /* Start Timer (just to be sure that at least one request is sent. */
  156.   /*          CheckIO doesn't work otherwise, i think) */
  157.  
  158.   QueueTimer();
  159.  
  160.   /********************
  161.    * Make a semaphore *
  162.    ********************/
  163.   PopUpSemaphore.ss_Link.ln_Name = SEMAPHORENAME;
  164.   PopUpSemaphore.ss_Link.ln_Pri  = 0;
  165.   AddSemaphore(&PopUpSemaphore);
  166.  
  167.   /**************************************************
  168.    * patch intuition functions to use our semaphore *
  169.    **************************************************/
  170.   if (!(OldSetMenuStrip = SetFunction((struct Library *)IntuitionBase,
  171.                       LVOSetMenuStrip,MySetMenuStrip)))
  172.     goto CleanUp2x4;
  173.   if (!(OldClearMenuStrip = SetFunction((struct Library *)IntuitionBase,
  174.                     LVOClearMenuStrip,MyClearMenuStrip)))
  175.     goto CleanUp2x3;
  176.   if (!(OldOnMenu = SetFunction((struct Library *)IntuitionBase,
  177.                 LVOOnMenu,MyOnMenu)))
  178.     goto CleanUp2x2;
  179.   if (!(OldOffMenu = SetFunction((struct Library *)IntuitionBase,
  180.                  LVOOffMenu,MyOffMenu)))
  181.     goto CleanUp2x1;
  182.  
  183.   /**********************************
  184.    * init data for the inputhandler *
  185.    **********************************/
  186.   InputSignals.PopUpMenuTask = FindTask(0);
  187.   InputSignals.MenuUpSig     = 1L << MenuUpSigNum;
  188.   InputSignals.MenuDownSig   = 1L << MenuDownSigNum;
  189.   InputSignals.MouseMovedSig = 1L << MouseMovedSigNum;
  190.   InputSignals.SelectDownSig = 1L << SelectDownSigNum;
  191.   InputSignals.Down         = FALSE;  /* menubutton is not down. (who cares) */
  192.  
  193.   /****************************
  194.    * startup the inputhandler *
  195.    ****************************/
  196.   InputReqData.is_Node.ln_Pri  = INPHANDLPRI;        /* must come before intuition */
  197.   InputReqData.is_Node.ln_Name = INPHANDLNAME;
  198.  
  199.   InputReqData.is_Data           = (APTR)&InputSignals;
  200.   InputReqData.is_Code           = (VOID *)PopUpHandler;
  201.  
  202.   InputReqBlock->io_Command = IND_ADDHANDLER;
  203.   InputReqBlock->io_Data    = (APTR)&InputReqData;
  204.  
  205.   DoIO((struct IORequest *)InputReqBlock);
  206.  
  207.   /***************************************
  208.    * tell the user that everything is ok *
  209.    ***************************************/
  210.   WriteAndClose(VERSION STARTMSG, sizeof(VERSION STARTMSG));
  211.  
  212.   PopUpMainLoop(&InputSignals,ReplyPort);
  213.  
  214. CleanUp1:
  215.  
  216.   /* remove inputhandler */
  217.   InputReqBlock->io_Command = IND_REMHANDLER;
  218.   InputReqBlock->io_Data    = (APTR)&InputReqData;
  219.  
  220.   DoIO((struct IORequest *)InputReqBlock);
  221.  
  222.   /* restore intuition functions */
  223.   SetFunction((struct Library *)IntuitionBase,LVOOffMenu,OldOffMenu);
  224. CleanUp2x1:
  225.   SetFunction((struct Library *)IntuitionBase,LVOOnMenu,OldOnMenu);
  226. CleanUp2x2:
  227.   SetFunction((struct Library *)IntuitionBase,LVOClearMenuStrip,OldClearMenuStrip);
  228. CleanUp2x3:
  229.   SetFunction((struct Library *)IntuitionBase,LVOSetMenuStrip,OldSetMenuStrip);
  230. CleanUp2x4:
  231.  
  232.   /* remove semaphore */
  233.   RemSemaphore(&PopUpSemaphore);
  234.  
  235.   /* close timer.device */
  236.   CloseDevice((struct IORequest *)TimerReqBlock);
  237. CleanUp3x1:
  238.   FreeMem(TimerReqBlock,sizeof(struct timerequest));
  239. CleanUp3x2:
  240.   DeletePort(TimerPort);
  241. CleanUp3x3:
  242.  
  243.   /* close input.device */
  244.   CloseDevice((struct IORequest *)InputReqBlock);
  245. CleanUp3:
  246.   DeleteStdIO(InputReqBlock);
  247. CleanUp4:
  248.   DeletePort(InputDevPort);
  249. CleanUp5:
  250.  
  251.   /* Free allocated signals */
  252.   FreeSignal(SelectDownSigNum);
  253. CleanUp6:
  254.   FreeSignal(MouseMovedSigNum);
  255. CleanUp7:
  256.   FreeSignal(MenuDownSigNum);
  257. CleanUp8:
  258.   FreeSignal(MenuUpSigNum);
  259. CleanUp9:
  260.  
  261.   /* close libraries */
  262.   CloseLibrary((struct Library *)LayersBase);
  263. CleanUp10:
  264.   CloseLibrary((struct Library *)GfxBase);
  265. CleanUp11:
  266.   CloseLibrary((struct Library *)IntuitionBase);
  267. CleanUp12:
  268.   DeletePort(ReplyPort);
  269. CleanUp13:
  270.   if (StdOut)
  271.     WriteAndClose(FAILMSG,sizeof(FAILMSG));
  272.   if (PopUpSeg) {
  273.     /* if loaded from CLI unload us */
  274.     Forbid();
  275.     UnLoadSeg(PopUpSeg);
  276.   }
  277.   CloseLibrary((struct Library *)DOSBase);
  278. }
  279.  
  280. /***************************************
  281.  * WriteAndClose(Text,Length)          *
  282.  *                       *
  283.  * Input:                   *
  284.  *   Text   - Text to write to StdOut. *
  285.  *   Length                   *
  286.  ***************************************/
  287. VOID WriteAndClose(Text, Length)
  288.   STRPTR Text;
  289.   ULONG Length;
  290. {
  291.   IMPORT BPTR StdOut;
  292.  
  293.   Write(StdOut,Text,Length);
  294.   Delay(DELAYTIME);
  295.   Close(StdOut);
  296.   StdOut = NULL;
  297. }
  298.  
  299. /************************************************
  300.  * PopUpMainLoop(InputSignals,ReplyPort)        *
  301.  *                        *
  302.  * Input:                    *
  303.  *   InputSignals - Allocated signals.        *
  304.  *   ReplyPort      - Port for MENUVERIFY replies *
  305.  * Output:                    *
  306.  *   none                    *
  307.  ************************************************/
  308. VOID PopUpMainLoop(InputSignals,ReplyPort)
  309.   struct SignalData *const InputSignals;
  310.   struct MsgPort *const ReplyPort;
  311. {
  312.   IMPORT struct Window    *ActiveWindow;
  313.   IMPORT struct Screen    *Screen;
  314.   IMPORT struct Menu    *Menues;
  315.  
  316.   const LONGBITS ReplySig    = 1L << (LONG)ReplyPort->mp_SigBit;
  317.   const LONGBITS MenuUpSig   = InputSignals->MenuUpSig;
  318.   const LONGBITS MenuDownSig = InputSignals->MenuDownSig;
  319.   const LONGBITS AllSignals  = ReplySig | MenuUpSig | MenuDownSig;
  320.  
  321.   WORD    NrOfMessages = 0;
  322.   BOOL    QuitPopUpMenu = FALSE;
  323.   BOOL    VerifyOK = FALSE;
  324.  
  325.   FOREVER {
  326.     const LONGBITS SignalBits = Wait(AllSignals);
  327.  
  328.     if (SignalBits & MenuUpSig) {
  329.       ActiveWindow = NULL;
  330.       VerifyOK       = FALSE;
  331.     }
  332.  
  333.     if (SignalBits & ReplySig) {
  334.       struct IntuiMessage *Message;
  335.  
  336.       while (Message = (struct IntuiMessage *)GetMsg(ReplyPort)) {
  337.     if (Message->Class == MENUVERIFY) {
  338.       if (Message->IDCMPWindow == ActiveWindow)
  339.         VerifyOK = (Message->Code != MENUCANCEL);
  340.       NrOfMessages--;
  341.       FreeMem(Message,(LONG)Message->ExecMessage.mn_Length +
  342.                   sizeof(struct Message));
  343.     }
  344.     else { /* Message->Class == QUITPOPUPMENU or some strange message */
  345.       ReplyMsg((struct Message *)Message); /* Message does not belong to this task */
  346.       QuitPopUpMenu = TRUE;
  347.     }
  348.  
  349.       } /* while */
  350.       if (NrOfMessages == 0) {
  351.     if (QuitPopUpMenu)
  352.       break;
  353.     if (VerifyOK) {
  354.       PopUpMenu(InputSignals);
  355.       VerifyOK = FALSE;
  356.     }
  357.       }
  358.     }
  359.  
  360.     if ((SignalBits & (MenuUpSig | MenuDownSig)) == MenuDownSig) {
  361.       const LONG  Lock = LockIBase(0);
  362.  
  363.       if ((ActiveWindow = IntuitionBase->ActiveWindow) AND
  364.      !(ActiveWindow->Flags & RMBTRAP) AND
  365.      (ActiveWindow->MenuStrip)) {
  366.     Screen = ActiveWindow->WScreen;
  367.     UnlockIBase(Lock);
  368.     if ((NrOfMessages = SendMessage(ReplyPort)) == 0)
  369.       PopUpMenu(InputSignals);
  370.     else
  371.       VerifyOK = TRUE;
  372.       }
  373.       else
  374.     UnlockIBase(Lock);
  375.     }
  376.   } /* FOREVER */
  377. }
  378.